package com.simple.relaxed.anno.impl;

import com.simple.relaxed.anno.Config;
import com.simple.relaxed.anno.TaskUnit;
import com.simple.relaxed.manager.impl.ConfigManager;
import com.simple.relaxed.utils.ReflectionsUtil;
import ohos.app.Context;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.app.dispatcher.task.Revocable;
import ohos.app.dispatcher.task.TaskPriority;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class ConfigImpl {

    /**
     * 调用此方法，发现@Config标记的类，被标记的类，会在框架的所有功能逻辑执行之前触发，实例化被标记的类，寻找被@TaskUnit注解标记的方法，并且将其放到非UI线程中触发
     *
     * @param context 上下文对象，必不可少，使用此对象获取的执行堆栈对象
     * @throws NoSuchMethodException     找不到指定方法时，抛出此异常
     * @throws IllegalAccessException    调用方法时，输入参数错误时，抛出此异常
     * @throws InvocationTargetException 反射调用方法产生错误时，抛出此异常
     * @throws InstantiationException    反射实例化失败时，抛出此异常
     */
    public static void configImpl(Context context) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Set<Class<?>> classes = ReflectionsUtil.getClassByAnnotationClass(Config.class);
        if (classes == null) {
            return;
        }
        TaskDispatcher taskDispatcher = context.getGlobalTaskDispatcher(TaskPriority.DEFAULT);
        for (Class<?> cls : classes) {
            Constructor<?> constructor = cls.getDeclaredConstructor();
            Object instance = constructor.newInstance();
            Method[] methods = cls.getDeclaredMethods();
            List<Revocable> revocables = new ArrayList<>();
            for (Method method : methods) {
                TaskUnit taskUnit = method.getDeclaredAnnotation(TaskUnit.class);
                if (taskUnit == null) {
                    continue;
                }
                Revocable revocable = taskDispatcher.asyncDispatch(() -> {
                    try {
                        method.setAccessible(true);
                        int parameterCount = method.getParameterCount();
                        if (parameterCount == 1) {
                            method.invoke(instance, context);
                        } else {
                            method.invoke(instance);
                        }
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                });
                revocables.add(revocable);
            }
            ConfigManager.getInstance().register(cls, revocables);
        }
    }
}
